import _Const from '@/Const';
import { Message } from 'element-ui';
import i18n from '@/lang';
/**
 * 获取url中的参数
 * @create 2019-10-30
 * @author skyinzhang
 * @params name 需要从url中获取的字段名称
 * @describe 获取url中的参数
 */
export const getQueryString = (name: string) => {
  const reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)', 'i');
  const r = window.location.search.substr(1).match(reg);
  if (r != null) return unescape(r[2]);
  return null;
};

/**
 * vue 获取url中的参数
 * @create 2019-10-30
 * @author skyinzhang
 * @params name 需要从url中获取的字段名称
 * @describe 获取url中的参数
 */
export const getUrlKey = (name: string) => {
  const reg: any = new RegExp('[?|&]' + name + '=' + '([^&;]+?)(&|#|;|$)');
  const str: any = (reg.exec(location.href) || [, ''])[1].replace(/\+/g, '%20');
  return decodeURIComponent(str) || null;
};

/**
 * 将json对象转换为 FormData类型
 * @param data 【参数是json对象】
 * @return [返回 FormData类型 的值]
 */
export const transformDataToFormData = (data: any) => {
  console.log(' axios  将参数转为 formdata 类型  >>>>>>>>> ', data);
  const form = new FormData();
  Object.keys(data).forEach((key) => {
    console.log(' (data[key] instanceof Array)  >>>>>>>>> ', data[key] instanceof Array);
    console.log('key >>>>>>>>>: ', key);
    console.log('data[key] >>>>>>>>>: ', data[key]);
    if (data[key] instanceof Array) {
      data[key].forEach((value: any) => {
        form.append(key, value);
      });
    } else {
      form.append(key, data[key]);
    }
  });

  console.log('form >>>>>>>>>: ', form);
  return form;
};

/**
 * 存储 localStorage
 */
export const setLS = (name: string, content: string) => {
  if (!name) return;
  if (typeof content !== 'string') {
    content = JSON.stringify(content);
  }
  window.localStorage.setItem(name, content);
};

/**
 * 获取 localStorage
 */
export const getLS = (name: string) => {
  if (!name) return;
  return JSON.parse(window.localStorage.getItem(name));
};

/**
 * 删除 localStorage
 */
export const removeLS = (name: string) => {
  if (!name) return;
  window.localStorage.removeItem(name);
};

/**
 * 存储 sessionStorage
 */
export const sessionStorageSet = (name: any, content: any) => {
  if (!name) return;
  if (typeof content !== 'string') {
    content = JSON.stringify(content);
  }
  window.sessionStorage.setItem(name, content);
};

/**
 * 获取 sessionStorage
 */
export const sessionStorageGet = (name: any) => {
  if (!name) return;
  return window.sessionStorage.getItem(name);
};

/**
 * 删除 sessionStorage
 */
export const sessionStorageRemove = (name: string) => {
  if (!name) return;
  window.sessionStorage.removeItem(name);
};

/**
 * 获取 路由 键值对
 * @params IGetRoutObj
 * @return
 */
declare interface IGetRoutObj {
  path: string;
  name: string;
}
declare interface IGetRoutObjRtn<T = IGetRoutObj> {
  path: string;
  children: T[];
}
export const getRoutObj = (childRoutObj: any) => {
  const routePropObj: IGetRoutObjRtn = {
    path: '',
    children: [],
  };

  // 设置 父级 path 名字
  routePropObj.path = childRoutObj.path;

  // 设置 子级 路由
  childRoutObj.children.map((item: any) => {
    let path = item.path;
    if (path.indexOf('/') < 0) {
      path = `/${item.path}`;
    }
    const itemObj = {
      name: item.name,
      path: path,
    };
    routePropObj.children.push(itemObj);
  });

  return routePropObj;
};

/**
 * 保留小数点 2 位
 * @params value
 * @return
 */
export const returnFloat = (val: any) => {
  let value: any = Math.round(parseFloat(val) * 100) / 100;
  const s = value.toString().split('.');
  if (s.length == 1) {
    value = value.toString() + '.00';
    return value;
  }
  if (s.length > 1) {
    if (s[1].length < 2) {
      value = value.toString() + '0';
    }
    return value;
  }
};

// 金额千分位
export const moneyFor = (n) => {
  if (!n) return n === 0 ? String(n) : n;
  n = String(n).trim();
  const regex = /^-?(\d{1,3}(,\d{3})*|\d+)(\.\d+)?$/;
  if (!regex.test(n)) {
    Message.error(i18n.t('无效的金额格式'));
    return null;
  }
  n = String(n).replace(/,/g, '');
  const str = String(n).split('.');
  str[1] = str[1] && str[1].length === 1 ? `${str[1]}0` : str[1];
  const re = /\d{1,3}(?=(\d{3})+$)/g;
  const n1 = str[0].replace(re, '$&,');
  return str.length > 1 && str[1] ? `${n1}.${str[1]}` : `${n1}.00`;
};

//去除千分位中的‘，'
export const delcommafy = function (num) {
  if (!num) return num;
  num = num.toString();
  num = num.replace(/,/gi, '');
  return num;
};

// 获取当前日期
export function getTimer() {
  const T = new Date();
  const Year: number | string = T.getFullYear();
  let Month: number | string = T.getMonth();
  if (Month < 9) {
    Month = `0${Month + 1}`;
  } else {
    Month = Month + 1;
  }
  return Year + '-' + Month;
}

// 获取当前月份的上一个月
export const getPreMonth = (date) => {
  const arr = date.split('-');
  const year = arr[0]; //获取当前日期的年份
  const month = arr[1]; //获取当前日期的月份
  let days: any = new Date(year, month, 0);
  days = days.getDate(); //获取当前日期中月的天数
  let year2 = year;
  let month2: any = parseInt(month) - 1;
  if (month2 == 0) {
    year2 = parseInt(year2) - 1;
    month2 = 12;
  }

  if (month2 < 10) {
    month2 = '0' + month2;
  }
  const t2 = year2 + '-' + month2;
  return t2;
};

export function formatDate(numb, format) {
  //  时间戳转换格式   （时间戳，  格式 yyyy-mm-dd 类型）
  const time: any = new Date((numb - 1) * 24 * 3600000 + 1);
  time.setYear(time.getFullYear() - 70);
  const year = time.getFullYear() + '';
  const month: any = time.getMonth() + 1 + '';
  const date: any = time.getDate() - 1 + '';
  if (format && format.length === 1) {
    return year + format + month + format + date;
  }
  return year + (month < 10 ? '0' + month : month) + (date < 10 ? '0' + date : date);
}

export function toFixed(x) {
  // 科学计算法解析
  if (Math.abs(x) < 1.0) {
    const e = parseInt(x.toString().split('e-')[1]);
    if (e) {
      x *= Math.pow(10, e - 1);
      x = '0.' + new Array(e).join('0') + x.toString().substring(2);
    }
  } else {
    let e = parseInt(x.toString().split('+')[1]);
    if (e > 20) {
      e -= 20;
      x /= Math.pow(10, e);
      x += new Array(e + 1).join('0');
    }
  }
  return x;
}

export function formatDateTime(date) {
  // 时间转换为 yyyy/mm-dd 00：00：00
  const y = date.getFullYear();
  let m = date.getMonth() + 1;
  m = m < 10 ? '0' + m : m;
  let d = date.getDate();
  d = d < 10 ? '0' + d : d;
  const h = date.getHours();
  let minute = date.getMinutes();
  minute = minute < 10 ? '0' + minute : minute;
  return y + '/' + m + '/' + d + ' ' + h + ':' + minute;
}

//数字转中文
export function toChinesNum(num) {
  const changeNum = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九'];
  const unit = ['', '十', '百', '千', '万'];
  num = parseInt(num);
  const getWan = (temp) => {
    const strArr = temp.toString().split('').reverse();
    let newNum = '';
    const newArr: any = [];
    strArr.forEach((item, index) => {
      newArr.unshift(item === '0' ? changeNum[item] : changeNum[item] + unit[index]);
    });
    const numArr: any = [];
    newArr.forEach((m, n) => {
      if (m !== '零') numArr.push(n);
    });
    if (newArr.length > 1) {
      newArr.forEach((m, n) => {
        if (newArr[newArr.length - 1] === '零') {
          if (n <= numArr[numArr.length - 1]) {
            newNum += m;
          }
        } else {
          newNum += m;
        }
      });
    } else {
      newNum = newArr[0];
    }
    return newNum;
  };
  const overWan = Math.floor(num / 10000);
  let noWan = (num % 10000) + '';
  if (noWan.toString().length < 4) {
    noWan = '0' + noWan;
  }
  return overWan ? getWan(overWan) + '万' + getWan(noWan) : getWan(num);
}

export function optionNameToLabel(options, value) {
  const res = _Const[options].find((row) => row.value === value);
  return res && res.label;
}

export function valueToLabel(options, value) {
  const res = options.find((row) => row.value === value);
  return res && res.label;
}

// JS去除对象中值为undefined和null的空键值字段
export const setObjectNoUndef = (data: any = {}) => {
  const params = Object.keys(data)

    .filter((key) => data[key] !== null && data[key] !== undefined && data[key] !== '' && data[key].length !== 0)

    .reduce((acc, key) => ({ ...acc, [key]: data[key] }), {});
  return params;
};

// 获取年月的最后一天
export function getLastDayOfMonth(date) {
  if (!date) return '';
  const year = date.split('-')[0];
  const month = date.split('-')[1];
  const lastDay = new Date(year, month, 0).getDate(); // 设置结束日期为指定年月的最后一天
  const formattedDate = `${year}-${month.toString().padStart(2, '0')}-${lastDay.toString().padStart(2, '0')}`;
  return formattedDate;
}

// 首字母大写
export function capitalizeFirstLetter(str) {
  return str.charAt(0).toUpperCase() + str.slice(1);
}

// 首字母小写
export function lowercaseFirstLetter(str) {
  return str.charAt(0).toLowerCase() + str.slice(1);
}

// 初始化form
export function initForm(formColumn) {
  const form = {};
  for (let i = 0; i < formColumn.length; i++) {
    form[formColumn[i].name] = undefined;
  }
  return form;
}

export function resetFormItem(formModel: any, saveList: any = []) {
  const keys = Object.keys(formModel);
  if (!keys.length) return;
  keys.forEach((key) => {
    const type = Object.prototype.toString.call(formModel[key]);
    if (type === '[object Object]') {
      resetFormItem(formModel[key]);
    } else if (!saveList.includes(key)) {
      formModel[key] = undefined;
    }
  });
}

// 加减乘除
export const floatObj = () => {
  /*
   * 判断obj是否为一个整数 整数取整后还是等于自己。利用这个特性来判断是否是整数
   */
  function isInteger(obj) {
    // 或者使用 Number.isInteger()
    return Math.floor(obj) === obj;
  }
  /*
   * 将一个浮点数转成整数，返回整数和倍数。如 3.14 >> 314，倍数是 100
   * @param floatNum {number} 小数
   * @return {object}
   *   {times:100, num: 314}
   */
  function toInteger(floatNum: number) {
    // 初始化数字与精度 times精度倍数  num转化后的整数
    const ret = { times: 1, num: 0 };
    const isNegative = floatNum < 0; //是否是小数
    if (isInteger(floatNum)) {
      // 是否是整数
      ret.num = floatNum;
      return ret; //是整数直接返回
    }
    const strfi = floatNum + ''; // 转换为字符串
    const dotPos = strfi.indexOf('.');
    const len = strfi.substr(dotPos + 1).length; // 拿到小数点之后的位数
    const times: number = Math.pow(10, len); // 精度倍数
    /* 为什么加0.5?
            前面讲过乘法也会出现精度问题
            假设传入0.16344556此时倍数为100000000
            Math.abs(0.16344556) * 100000000=0.16344556*10000000=1634455.5999999999 
            少了0.0000000001
            加上0.5 0.16344556*10000000+0.5=1634456.0999999999 parseInt之后乘法的精度问题得以矫正
        */
    const str = Math.abs(floatNum) * times + 0.5;
    let intNum: number = parseInt(str + '', 10);
    ret.times = times;
    if (isNegative) {
      intNum = -intNum;
    }
    ret.num = intNum;
    return ret;
  }

  /*
   * 核心方法，实现加减乘除运算，确保不丢失精度
   * 思路：把小数放大为整数（乘），进行算术运算，再缩小为小数（除）
   * @param a {number} 运算数1
   * @param b {number} 运算数2
   */
  function operation(a, b, op) {
    const o1 = toInteger(a);
    const o2 = toInteger(b);
    const n1 = o1.num; // 3.25+3.153
    const n2 = o2.num;
    const t1 = o1.times;
    const t2 = o2.times;
    const max = t1 > t2 ? t1 : t2;
    let result: any = null;
    switch (op) {
      // 加减需要根据倍数关系来处理
      case 'add':
        if (t1 === t2) {
          // 两个小数倍数相同
          result = n1 + n2;
        } else if (t1 > t2) {
          // o1 小数位 大于 o2
          result = n1 + n2 * (t1 / t2);
        } else {
          // o1小数位小于 o2
          result = n1 * (t2 / t1) + n2;
        }
        return result / max;
      case 'subtract':
        if (t1 === t2) {
          result = n1 - n2;
        } else if (t1 > t2) {
          result = n1 - n2 * (t1 / t2);
        } else {
          result = n1 * (t2 / t1) - n2;
        }
        return result / max;
      case 'multiply':
        // 325*3153/(100*1000) 扩大100倍 ==>缩小100倍
        result = (n1 * n2) / (t1 * t2);
        return result;
      case 'divide':
        // (325/3153)*(1000/100)  缩小100倍 ==>扩大100倍
        result = (n1 / n2) * (t2 / t1);
        return result;
    }
  }

  // 加减乘除的四个接口
  function add(a: any, b: any) {
    return operation(a, b, 'add');
  }
  function subtract(a, b) {
    return operation(a, b, 'subtract');
  }
  function multiply(a, b) {
    return operation(a, b, 'multiply');
  }
  function divide(a, b) {
    return operation(a, b, 'divide');
  }
  return {
    add: add,
    subtract: subtract,
    multiply: multiply,
    divide: divide,
  };
};

// 判断对象属性是否存在
export function checkProperty(obj) {
  for (const key in obj) {
    if (obj.hasOwnProperty(key) && obj[key]) {
      return true;
    }
  }
  return false;
}
